package zjut.raymond.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import zjut.raymond.algorithm.CalculateResult;
import zjut.raymond.algorithm.WifiAlgorithm;
import zjut.raymond.common.ApiResult;
import zjut.raymond.common.ResultUtils;
import zjut.raymond.pojo.PDRLocation;
import zjut.raymond.pojo.ReferencePoint;
import zjut.raymond.pojo.WifiFingerprint;
import zjut.raymond.service.AccessPointService;
import zjut.raymond.service.PDRLocationService;
import zjut.raymond.service.ReferencePointService;
import zjut.raymond.service.WifiFingerprintService;

import java.util.*;

/**
 * @author Raymond
 */
@Controller
@RequestMapping("/location")
public class LocationController {
    Logger logger = LoggerFactory.getLogger(LocationController.class);
    @Autowired
    private WifiFingerprintService wifiFingerprintService;
    @Autowired
    private ReferencePointService referencePointService;
    @Autowired
    private PDRLocationService pdrLocationService;
    @Autowired
    private AccessPointService accessPointService;


    @RequestMapping(value = "/wifilocation", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public ApiResult location(@RequestParam("fingerprint") String fingerprint) {
        //从AP表中选择可用的AP
        HashSet<String> apMacSet = CollectorController.selectAccessPointMacs(accessPointService);
        //处理在线指纹,过滤AP
        Map<String, Object> onlineFingerprint = (Map<String, Object>) JSON.parse(fingerprint);
        onlineFingerprint.keySet().retainAll(apMacSet);
        logger.info("在线指纹为：{}", onlineFingerprint);

        //从数据库中提取离线指纹数据
        QueryWrapper<WifiFingerprint> wifiFingerprintQueryWrapper = new QueryWrapper<>();
        wifiFingerprintQueryWrapper.select("reference_point_id", "ap_rssi_avg_dev");
        List<Map<String, Object>> offlineFingerprints = wifiFingerprintService.listMaps(wifiFingerprintQueryWrapper);
        // for (Map<String, Object> map : maps) {
        //     String ap_rssi_avg_dev = (String) map.get("ap_rssi_avg_dev");
        //     List<WifiFeatures> maps1 = JSON.parseArray(ap_rssi_avg_dev, WifiFeatures.class);
        //     Map<String, WifiFeatures> mapList = WifiAlgorithm.listToMap(maps1);
        //     logger.info("map对象为：{}", mapList);
        //     for (String key : mapList.keySet()) {
        //         WifiFeatures wifiFeatures = mapList.get(key);
        //         double mean = wifiFeatures.getMean();
        //         double standardDeviation = wifiFeatures.getStandardDeviation();
        //         logger.info("mean:{}, std:{}", mean, standardDeviation);
        //     }
        // }
        // // logger.info("请求参数为：{}", fingerprint);
        //

        // //
        // // logger.info("指纹:{}", map);
        List<CalculateResult> weightedBayesianResults = WifiAlgorithm.weightedBayesianAlgorithm(offlineFingerprints, onlineFingerprint, 2);
        //  logger.info("计算结果:{}", calculateResults);
        Map<String, Double> weightedBayesianLocation = getWeightLocation(weightedBayesianResults);
        logger.info("加权贝叶斯定位结果：{}", weightedBayesianLocation);

        List<CalculateResult> bayesianAlgorithmResults = WifiAlgorithm.bayesianAlgorithm(offlineFingerprints, onlineFingerprint, 3);
        Map<String, Double> bayesianLocation = getWeightLocation(bayesianAlgorithmResults);
        logger.info("贝叶斯定位结果：{}", bayesianLocation);

        List<CalculateResult> wKNNAlgorithmResults = WifiAlgorithm.weightKNNAlgorithm(offlineFingerprints, onlineFingerprint, 3);
        Map<String, Double> wKNNLocation = getWeightLocation(wKNNAlgorithmResults);
        logger.info("WKNN定位结果：{}", wKNNLocation);

        return ResultUtils.successResult(weightedBayesianLocation);
    }

    private Map<String, Double> getWeightLocation(List<CalculateResult> calculateResults) {
        List<Integer> list = new ArrayList<>();
        for (CalculateResult calculateResult : calculateResults) {
            list.add(calculateResult.getReferenceId());
        }
        QueryWrapper<ReferencePoint> referencePointQueryWrapper = new QueryWrapper<>();
        referencePointQueryWrapper.select("id", "x", "y").in("id", list);
        List<ReferencePoint> referencePoints = referencePointService.list(referencePointQueryWrapper);
        // logger.info("坐标：{}", referencePoints);
        return WifiAlgorithm.getLocation(calculateResults, referencePoints);
    }

    @RequestMapping(value = "/pdrLocation", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public ApiResult uploadPDRLocation(@RequestParam("location") String location) {
        Map<String, Object> locationMap = (Map<String, Object>) JSON.parse(location);
        Integer x = (Integer) locationMap.get("x");
        Integer y = (Integer) locationMap.get("y");
        pdrLocationService.save(new PDRLocation(x, y, new Date()));
        return ResultUtils.successResult();
    }
}
